﻿using System.Security.Cryptography;
using System.Text;

namespace StudyCompanion.Commons.Encrypt;

public class AesEncryption
{
    private const string _Key = "Shanghai_CaoHeJing_20210521_2137";
    private const string _IV = "_20210522202718_";

    /// <summary>
    ///     使用指定的Key和IV加密字符串
    /// </summary>
    /// <param name="plainText">加密字符串</param>
    /// <returns>字符串加密后的密文</returns>
    public static string Encrypt(string plainText)
    {
        if (plainText == null || plainText.Length <= 0)
            throw new ArgumentNullException(nameof(plainText));
        return AesEncrypt(plainText, _Key, _IV);
    }

    /// <summary>
    ///     把字符串original加密
    /// </summary>
    /// <param name="plainText">需要加密的字符串</param>
    /// <param name="Key">加密密钥</param>
    /// <param name="IV">加密向量</param>
    /// <returns>加密后的密文</returns>
    private static string AesEncrypt(string plainText, string Key, string IV)
    {
        var key = Encoding.UTF8.GetBytes(Key);
        var iv = Encoding.UTF8.GetBytes(IV);
        byte[] encrypted;

        using (var aes = Aes.Create())
        {
            aes.Key = key;
            aes.IV = iv;

            var transform = aes.CreateEncryptor();

            using MemoryStream stream = new();
            using CryptoStream crypto = new(stream, transform, CryptoStreamMode.Write);
            using StreamWriter writer = new(crypto);
            writer.Write(plainText);
            encrypted = stream.ToArray();
        }

        return Convert.ToBase64String(encrypted);
    }

    /// <summary>
    ///     使用指定的Key和IV进行解密
    /// </summary>
    /// <param name="cipherText">需要解密的密文</param>
    /// <returns>解密后的明文</returns>
    public static string Decrypt(string cipherText)
    {
        if (cipherText == null || cipherText.Length <= 0)
            throw new ArgumentNullException(nameof(cipherText));
        return AesDecrypt(cipherText, _Key, _IV);
    }

    /// <summary>
    ///     把字符串encrypted解密
    /// </summary>
    /// <param name="cipherText">需要解密的密文</param>
    /// <param name="Key">加密密钥</param>
    /// <param name="IV">加密向量</param>
    /// <returns>解密后的明文</returns>
    private static string AesDecrypt(string cipherText, string Key, string IV)
    {
        var data = Convert.FromBase64String(cipherText);
        var key = Encoding.UTF8.GetBytes(Key);
        var iv = Encoding.UTF8.GetBytes(IV);

        var original = string.Empty;

        using (var aes = Aes.Create())
        {
            aes.Key = key;
            aes.IV = iv;

            var transform = aes.CreateDecryptor();

            using MemoryStream stream = new(data);
            using CryptoStream crypto = new(stream, transform, CryptoStreamMode.Read);
            using StreamReader reader = new(crypto);
            original = reader.ReadToEnd();
        }

        return original;
    }
}